// 常量定义
const DOM_SELECTORS = {
  // 按钮
  submitBtn: "#submitBtn",
  clearBtn: "#clearBtn",
  closeDrawerBtn: "#closeDrawerBtn",
  // 输入URL元素
  urlInput: "#urlInput",
  // 分析结果显示元素
  resultContainer: "#resultContainer",
  // 基本信息元素
  basicInfoContainer: "#basicInfoContainer",
  basicNumber: "#basicNumber",
  basicBranch: "#basicBranch",
  basicChangeId: "#basicChangeId",
  basicCreated: "#basicCreated",
  basicStatus: "#basicStatus",
  basicSubject: "#basicSubject",
  basicSubmitter: "#basicSubmitter",
  // 文件变动元素
  filesTableContainer: "#filesTableContainer",
  filesTableBody: "#filesTableBody",
  connectionResult: "#connectionResult",
  // 检测结果元素
  workflowContainer: "#workflowContainer",
  workflowResults: "#workflowResults",
  issuesList: "#issuesList",
  issuesTable: "#issuesTable",
  analyseTableBody: "#analyseTableBody",
  prevBtn: "#prevBtn",
  nextBtn: "#nextBtn",
  pageNumbersContainer: "#page-numbers",
  searchBox: ".search-box",
  rankFilter: ".rank-filter",
  fileFilter: ".file-filter",
  datatable: "#data-table",
  // 导出按钮
  exportExcelBtn: "#exportExcelBtn",
  // 抽屉元素
  drawerContainer: "#drawerContainer",
  snippetPreview: "#snippetPreview",
  suggestTip: "#suggestTip",
  typeDisplay: "#typeDisplay",
  idDisplay: "#idDisplay",
  descDisplay: "#descDisplay",
  rangeDisplay: "#rangeDisplay",
  filenameDisplay: "#filenameDisplay",
  // 浮窗元素
  tooltip: "#detailTooltip",
  tooltipContent: ".tooltip-content",
  tooltipsnippetPreview: "#tooltip-snippetPreview",
  tooltipsuggestTip: "#tooltip-suggestTip",
  // 饼状图元素
  issuesDistributionContainer: "#issuesDistributionContainer",
  issuesDistributionChartPie: "#issuesDistributionChartPie",
  centerText: "#centerText",
  // 格式验证文本
  validationHint: "#validationHint",
  // 解析内容选项
  analysisOptions: "#analysisOptions",
  enableStaticEngine: "#enableStaticEngine",
  ignoreLevelB: "#ignoreLevelB",
  ignoreLevelC: "#ignoreLevelC",
  // 中央弹窗提示
  popup: "#approvalPopup",
  okBtn: "#okBtn",
};
// API 配置
const API_BASE_URL = "http://10.246.148.138:7070";
const API_ENDPOINTS = {
  changeInfo: "/change_info",
  analyse: "/analyse",
  accountInfo: "/account_info",
};
// URL 验证正则
const URL_PATTERN = /^http:\/\/gerrit-sh\.noboauto\.com:8090\/.*\/\+\/\d+$/;
// 时间提取正则
const TIME_PATTERN = /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/;
// 全局元素对象
let elements = {};
let issue_details_datas = [];
let issuesDistributionInstancePie = null;
let issuesDistributionInstanceBar = null;
// 状态样式映射
const STATUS_CLASSES = {
  MERGED: "status-merged",
  OPEN: "status-open",
  ABANDONED: "status-abandoned",
  NEW: "status-open",
};
//问题等级样式映射
const TYPE_CLASSES = {
  S级: "level-S",
  A级: "level-A",
  B级: "level-BC",
  C级: "level-BC",
};
// 饼状图中心文本样式映射
const CENTERTEXT_CLASSES = {
  S级: "ef4444",
  A级: "f59e0b",
  "B/C级": "2563eb",
};
let critical_issues = [];
let high_risk_issues = [];
let code_quality_issues = [];
let unique_filenames = new Set();
let same_ruleid_counts_map = new Map();
// 分页信息
let currentPage = 1;
let itemsPerPage = 6;
let totalItems = 0;
let totalPages = 1;
// 排序数据
let filteredData = [];
let sortField = "type";
let sortDirection = "asc";
// 浮窗显示影响参数
let timer = null;
let currentmouseRow = null;
let is_drawerOpen = false;

// 工具函数
function loadDOMElements() {
  elements = Object.entries(DOM_SELECTORS).reduce((acc, [key, selector]) => {
    const el = document.querySelector(selector);
    if (!el) {
      console.error(`缺失元素: ${selector}`);
      return acc;
    }
    return { ...acc, [key]: el };
  }, {});
}

// 设置按钮状态
function setButtonState(button, disabled, text) {
  button.disabled = disabled;
  // 先检查元素是否存在
  const btnText = button.querySelector(".btn-text");
  const spinner = button.querySelector(".loading-spinner");

  // 只有在元素存在的情况下才操作
  if (btnText && text !== undefined) {
    btnText.textContent = text;
  }

  if (btnText && spinner) {
    if (disabled) {
      spinner.style.display = "inline-block";
      btnText.style.display = "none";
    } else {
      spinner.style.display = "none";
      btnText.style.display = "inline-block";
    }
  }
}

function showWithAnimation(element) {
  element.style.display = "block";
  // 触发重排后添加动画类
  setTimeout(() => {
    element.classList.add("fade-in");
  }, 10);
}

// 清除之前的结果
function clearPreviousResults() {
  //清空问题内容
  issue_details_datas = [];
  critical_issues = [];
  high_risk_issues = [];
  code_quality_issues = [];
  //分页信息
  currentPage = 1;
  itemsPerPage = 6;
  totalItems = 0;
  totalPages = 1;
  filteredData = [];
  sortField = "type";
  sortDirection = "asc";
  elements.rankFilter.value = "";
  elements.fileFilter.value = "";

  //清空分析结果区域
  elements.connectionResult.textContent = "";
  //清空基础信息区域
  elements.basicNumber.textContent = "";
  elements.basicBranch.textContent = "";
  elements.basicChangeId.textContent = "";
  elements.basicCreated.textContent = "";
  elements.basicStatus.textContent = "";
  elements.basicSubject.textContent = "";
  elements.basicSubmitter.textContent = "";
  // 隐藏基础信息区域
  elements.basicInfoContainer.style.display = "none";
  // 清空文件变动区域
  elements.filesTableBody.innerHTML = "";
  // 隐藏文件变动区域
  elements.filesTableContainer.style.display = "none";
  // 清空工作流分析结果区域
  elements.workflowResults.textContent = "";
  // 清空工作流区域
  elements.filesTableBody.innerHTML = "";
  elements.analyseTableBody.innerHTML = "";
  // 清空浮窗内容
  elements.tooltipsnippetPreview.textContent = "";
  elements.tooltipsuggestTip.textContent = "";
  // 隐藏工作流区域
  elements.workflowContainer.style.display = "none";
  elements.issuesDistributionContainer.style.display = "none";
  elements.validationHint.textContent = "";
  // 清空抽屉内容
  elements.snippetPreview.innerHTML = "";
  elements.suggestTip.innerHTML = "";
  elements.typeDisplay.textContent = "";
  elements.idDisplay.textContent = "";
  elements.descDisplay.textContent = "";
  elements.rangeDisplay.textContent = "";
  elements.filenameDisplay.textContent = "";
  elements.connectionResult.textContent = "";
  elements.issuesDistributionContainer.style.display = "none";
  // 关闭抽屉
  closeDrawer();
  // 清空验证显示文本
  elements.validationHint.textContent = "";
  // 重置动画状态
  [
    elements.basicInfoContainer,
    elements.filesTableContainer,
    elements.workflowContainer,
    elements.issuesDistributionContainer,
  ].forEach((el) => {
    el.classList.remove("fade-in");
    el.style.opacity = "0";
    el.style.transform = "translateY(10px)";
  });
}

// 更新清空按钮显示状态
function updateClearButtonVisibility() {
  const hasContent = elements.urlInput.value.trim() !== "";
  if (hasContent) {
    elements.clearBtn.classList.add("visible");
  } else {
    elements.clearBtn.classList.remove("visible");
  }
}

// 清空输入框内容
function clearInput() {
  elements.urlInput.value = "";
  updateClearButtonVisibility();
  elements.urlInput.focus();
}
// 关闭抽屉
function closeDrawer() {
  elements.drawerContainer.classList.remove("open");
  // 动画结束后隐藏
  setTimeout(() => {
    elements.drawerContainer.style.display = "none";
  }, 300);
  is_drawerOpen = false;
}

  // 实时验证URL
function validateUrlOnInput(url) {
  if (!url) {
    elements.validationHint.textContent = "";
    return;
  }
  if (!URL_PATTERN.test(url)) {
    elements.validationHint.textContent =
      "⚠️ URL格式不正确，必须为Gerrit代码提交链接";
  } else {
    elements.validationHint.textContent = "✓ 格式正确";
    elements.validationHint.style.color = "var(--accent-color)";
  }
}
// 通用api请求
async function fetchApi(endpoint, data = {}) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 2400000); // 40min超时

  try {
    const formData = new FormData();
    Object.entries(data).forEach(([key, value]) => {
      if (typeof value === "object" && !(value instanceof File)) {
        formData.append(key, JSON.stringify(value));
      } else {
        formData.append(key, value);
      }
    });

    const response = await fetch(`${API_BASE_URL}${endpoint}`, {
      method: "POST",
      body: formData,
      signal: controller.signal,
    });

    clearTimeout(timeoutId);
    const result = await response.json();
    // HTTP状态码处于200-299之间，返回true
    console.log(response);
    if (!response.ok) {
      throw new Error(result.message);
    }

    if (!result.message) {
      throw new Error("接口返回格式异常");
    }
    return result.message;
  } catch (error) {
    throw error;
  }
}

// 添加 HTML 转义函数
function escapeHtml(unsafe) {
  if (!unsafe) return '';
  return unsafe
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

function appendIssueRow(issue, parent) {
  const row = document.createElement("tr");
  row.innerHTML = `
    <td class="issue-type ${TYPE_CLASSES[issue.type]}">${issue.type}</td>
    <td class="rule-id">${issue.rule_id}</td>
    <td>${escapeHtml(issue.description)}</td>
    <td><b>[${issue.line_range}]</b></td>
    <td>${issue.filename}</td>
    `;
  parent.appendChild(row);
}

// 显示抽屉函数
function showDrawer(issue) {
  elements.drawerContainer.style.display = "block";
  // 延迟添加open类触发动画
  setTimeout(() => {
    elements.drawerContainer.classList.add("open");
  }, 10);
  // 填充内容
  elements.snippetPreview.innerHTML = escapeHtml(issue.code_snippet);
  elements.suggestTip.innerHTML = escapeHtml(issue.advice);
  elements.typeDisplay.textContent = issue.type;
  elements.idDisplay.textContent = issue.rule_id;
  elements.descDisplay.textContent = issue.description;
  elements.rangeDisplay.textContent = `[${issue.line_range}]`;
  elements.filenameDisplay.textContent = issue.filename;
}

// 动态渲染问题表格
function renderIssueList(issues) {
  elements.issuesList.style.display = "block";
  issues_number =
    issues["critical_issues"].length +
    issues["high_risk_issues"].length +
    issues["code_quality_issues"].length;
  let question_info = "总问题个数：" +
    issues_number +
    "个\nS级问题个数：" +
    issues["critical_issues"].length +
    "个\nA级问题个数：" +
    issues["high_risk_issues"].length +
    "个\nB级问题个数：" +
    issues["code_quality_issues"].length +
    "个";

  initchart(
    issues["critical_issues"].length,
    issues["high_risk_issues"].length,
    issues["code_quality_issues"].length,
    issues_number
  );
  critical_issues = issues["critical_issues"];
  high_risk_issues = issues["high_risk_issues"];
  code_quality_issues = issues["code_quality_issues"];
  // 填充文件变动信息表格
  if (issues_number === 0) {
    const emptyRow = document.createElement("tr");
    emptyRow.innerHTML =
      '<td colspan="6" style="text-align: center; padding: 20px;">该代码没有异常问题</td>';
    elements.analyseTableBody.appendChild(emptyRow);
  } else {
    same_ruleid_counts_map = new Map();
    issues["critical_issues"].forEach((issue) => {
      const currentCount = same_ruleid_counts_map.get(issue.rule_id) || 0;
      if (currentCount < 10) {
        issue_details_datas.push(issue);
        unique_filenames.add(issue.filename);
      }
      same_ruleid_counts_map.set(issue.rule_id, currentCount + 1);
    });
    issues["high_risk_issues"].forEach((issue) => {
      const currentCount = same_ruleid_counts_map.get(issue.rule_id) || 0;
      if (currentCount < 10) {
        issue_details_datas.push(issue);
        unique_filenames.add(issue.filename);
      }
      same_ruleid_counts_map.set(issue.rule_id, currentCount + 1);
    });
    issues["code_quality_issues"].forEach((issue) => {
      const currentCount = same_ruleid_counts_map.get(issue.rule_id) || 0;
      if (currentCount < 10) {
        issue_details_datas.push(issue);
        unique_filenames.add(issue.filename);
      }
      same_ruleid_counts_map.set(issue.rule_id, currentCount + 1);
    });
    let rule_id_more_than_ten = [];
    same_ruleid_counts_map.forEach((count, rule_id) => {
      if (count >= 10) {
        rule_id_more_than_ten.push(rule_id);
      }
    });
    if (rule_id_more_than_ten.length > 0) {
      let same_ruleid_descriptions = "\n警告：\n\t其中规则";
      rule_id_more_than_ten.forEach((rule_id, index) => {
        same_ruleid_descriptions += `${rule_id}`;
        if (index < rule_id_more_than_ten.length - 1) {
          same_ruleid_descriptions += `, `;
        }
      });
      same_ruleid_descriptions +=
        " 有不小于10个同类型问题, 当前同类型问题均最多只显示10个, 请您仔细检查代码问题并重新提交 ！！！";
      setWorkflowResults([
        { type: 'info', text: question_info },
        { type: 'warning', text: same_ruleid_descriptions }
      ]);
    } else {
      setWorkflowResults([
        { type: 'info', text: question_info }
      ]);
    }
    // 动态添加下拉选项
    const select = document.querySelector(".file-filter");
    unique_filenames.forEach((filename) => {
      select.add(new Option(filename, filename));
    });

    totalItems = issue_details_datas.length;
    totalPages = Math.ceil(totalItems / itemsPerPage);
    currentPage = 1;
    renderissueTable(currentPage, issue_details_datas);
    filteredData = [...issue_details_datas];

    elements.prevBtn.addEventListener("click", () => {
      if (currentPage > 1) {
        // console.log("点击了上一页，页码减一");
        currentPage--;
        renderissueTable(currentPage, filteredData);
      }
    });

    elements.nextBtn.addEventListener("click", () => {
      if (currentPage < totalPages) {
        // console.log("点击了下一页，页码加一");
        currentPage++;
        renderissueTable(currentPage, filteredData);
      }
    });
  }

  tootipEvent();

  // 搜索框事件
  elements.searchBox.addEventListener("input", filterData);

  // 下拉筛选事件
  elements.rankFilter.addEventListener("change", filterData);
  elements.fileFilter.addEventListener("change", filterData);

  const tableHeaders = elements.datatable.querySelectorAll("th");
  tableHeaders.forEach((header) => {
    if (header.hasAttribute("data-sort")) {
      header.addEventListener("click", () => {
        headerclickEvent(header);
      });
    }
  });
}

function tootipEvent() {
  elements.datatable.addEventListener("click", (e) => {
    showdetails_Drawer(e);
    is_drawerOpen = true;
    elements.tooltip.classList.remove("show");
    currentmouseRow = null;
  });
  elements.datatable.addEventListener("mousemove", (e) => {
    // 判断鼠标是否进入了td元素
    if (e.target.tagName === "TD") {
      const newRow = e.target.closest("tr");
      if (newRow && newRow !== currentmouseRow) {
        // 只有当抽屉未打开时才显示tooltip
        if (!is_drawerOpen) {
          showdetails_Tooltip(e);
          currentmouseRow = newRow;
        }
      }
    }
  });
  elements.datatable.addEventListener("mouseout", (e) => {
    const currentTargetRow = e.target.closest("tr");
    if (currentTargetRow && currentTargetRow === currentmouseRow) {
      // 判断鼠标是否移动到了同一行的其他元素（比如同一行的其他td）
      const isMovingWithinRow =
        e.relatedTarget?.closest("tr") === currentmouseRow;
      if (!isMovingWithinRow) {
        clearTimeout(timer);
        if (!isMouseInTooltip()) {
          setTimeout(() => {
            if (!isMouseInTooltip()) {
              elements.tooltip.classList.remove("show");
            }
          }, 300);
        }
        currentmouseRow = null; // 重置当前行
      }
    }
  });
}

function isMouseInTooltip() {
  return elements.tooltip.matches(":hover");
}

function headerclickEvent(header) {
  // 如果点击的是当前排序的字段，则切换排序方向
  if (header.dataset.sort === sortField) {
    sortDirection = sortDirection === "asc" ? "desc" : "asc";
  } else {
    // 否则，设置新的排序字段，默认升序
    sortField = header.dataset.sort;
    sortDirection = "asc";
  }
  currentPage = 1;
  renderissueTable(currentPage, filteredData);
}

function showdetails_Drawer(e) {
  // 只给td添加点击事件（表格内容行）
  if (e.target.tagName === "TD") {
    const row = e.target.closest("tr");
    const rows = Array.from(elements.datatable.querySelectorAll("tr"));
    const rowIndex = rows.indexOf(row);
    const issue = filteredData[(currentPage - 1) * itemsPerPage + rowIndex - 1];
    showDrawer(issue);
  }
}
function showdetails_Tooltip(e) {
  // 只给td添加鼠标响应事件（表格内容行）
  timer = setTimeout(() => {
    const row = e.target.closest("tr");
    const rows = Array.from(elements.datatable.querySelectorAll("tr"));
    const rowIndex = rows.indexOf(row);
    const issue = filteredData[(currentPage - 1) * itemsPerPage + rowIndex - 1];
    elements.tooltipsnippetPreview.innerHTML = escapeHtml(issue.code_snippet);
    elements.tooltipsuggestTip.innerHTML = escapeHtml(issue.description);
    // 初始定位
    // positionTooltip(e);
    adjustFloatWindowNearMouse(e);
    showTooltip();
  }, 1000);
}

// 显示浮窗时确保过渡生效
function showTooltip() {
  const tooltip = elements.tooltip;
  tooltip.style.display = "block"; // 先显示
  setTimeout(() => {
    if (!is_drawerOpen) {
      tooltip.classList.add("show"); // 再触发过渡
    }
  }, 10);
}

// 定位浮窗函数 - 确保浮窗不会超出视口
function positionTooltip(e) {
  const tooltipWidth = elements.tooltip.offsetWidth;
  const tooltipHeight = elements.tooltip.offsetHeight;
  const windowWidth = window.innerWidth;
  const windowHeight = window.innerHeight;

  // 鼠标位置
  let x = e.clientX;
  let y = e.clientY;

  // 计算浮窗位置（鼠标右下方）
  let left = x + 10;
  let top = y + 10;

  // 检查右侧边界
  if (left + tooltipWidth > windowWidth) {
    left = x - tooltipWidth - 15;
  }

  // 检查底部边界
  if (top + tooltipHeight > windowHeight) {
    top = y - tooltipHeight - 15;
  }

  // 应用位置（考虑滚动偏移）
  elements.tooltip.style.left = `${left + window.scrollX}px`;
  elements.tooltip.style.top = `${top + window.scrollY}px`;
}

// 调整浮窗尺寸并定位在鼠标附近
function adjustFloatWindowNearMouse(e) {
  // 1. 先基于鼠标坐标设置初始位置（贴近鼠标）
  const mouseX = e.clientX; // 鼠标水平坐标（视口内）
  const mouseY = e.clientY; // 鼠标垂直坐标（视口内）
  const offset = 10; // 鼠标与浮窗的间距（避免遮挡鼠标）

  // 初始位置：鼠标右下方偏移offset像素
  elements.tooltip.style.left = `${mouseX + offset}px`;
  elements.tooltip.style.top = `${mouseY + offset}px`;

  // 2. 让浮窗自适应内容（移除固定宽高）
  elements.tooltip.style.width = 'auto';
  elements.tooltip.style.height = 'auto';

  // 3. 获取视口和浮窗的尺寸
  const viewportWidth = window.innerWidth;
  const viewportHeight = window.innerHeight;
  const contentWidth = elements.tooltip.offsetWidth;
  const contentHeight = elements.tooltip.offsetHeight;

  // 4. 限制浮窗最大尺寸（不超过视口的80%）
  const maxWidth = viewportWidth * 0.8;
  const maxHeight = viewportHeight * 0.8;
  const finalWidth = Math.min(contentWidth, maxWidth);
  const finalHeight = Math.min(contentHeight, maxHeight);

  // 应用计算后的尺寸
  elements.tooltip.style.width = `${finalWidth}px`;
  elements.tooltip.style.height = `${finalHeight}px`;

  // 5. 修正位置：确保浮窗在视口内，且尽量贴近鼠标
  const floatWidth = finalWidth;
  const floatHeight = finalHeight;

  // 计算基于鼠标的理想位置（可能超出视口）
  let idealLeft = mouseX + offset;
  let idealTop = mouseY + offset;

  // 边界调整：右侧超出则左移到鼠标左侧
  if (idealLeft + floatWidth > viewportWidth) {
    idealLeft = mouseX - floatWidth - offset;
  }

  // 边界调整：底部超出则上移到鼠标上方
  if (idealTop + floatHeight > viewportHeight) {
    idealTop = mouseY - floatHeight - offset;
  }

  // 最终限制：确保不超出视口边缘（极端情况）
  const constrainedLeft = Math.max(0, Math.min(idealLeft, viewportWidth - floatWidth));
  const constrainedTop = Math.max(0, Math.min(idealTop, viewportHeight - floatHeight));

  // 应用最终位置
  elements.tooltip.style.left = `${constrainedLeft}px`;
  elements.tooltip.style.top = `${constrainedTop}px`;
}

// Example function to set connection result with different highlight types
function setConnectionResult(message, type = 'info') {
  let prefix = '';
  switch (type) {
    case 'success':
      prefix = '√ ';
      break;
    case 'error':
      prefix = '× ';
      break;
    case 'warning':
      prefix = '! ';
      break;
    // case 'info':
    //     prefix = 'i ';
    //     break;
    default:
      prefix = '';
  }
  const highlightClass = `highlight-${type}`;
  const span = document.createElement('span');
  span.className = highlightClass;
  span.textContent = `${prefix}${message}`;
  elements.connectionResult.appendChild(span);
}

// Example function to set workflow results with multiple highlighted messages
function setWorkflowResults(messages) {
  let html = '';
  messages.forEach(msg => {
    html += `<span class="highlight-${msg.type}">${msg.text}</span>\n`;
  });
  elements.workflowResults.innerHTML = html;
}

async function submitdata() {
  const url = elements.urlInput.value.trim();
  // 清空之前的结果
  clearPreviousResults();

  if (!url) {
    setConnectionResult("请输入有效的链接!\n", "warning");
    return;
  }
  // 验证URL格式
  if (!URL_PATTERN.test(url)) {
    setConnectionResult("URL格式不正确，必须为Gerrit代码提交链接\n", "warning");
    return;
  }
  // 提取submitId
  const submitId = url.split("/+/")[1];
  const options = {
    enableStaticEngine: Number(elements.enableStaticEngine.checked),
    ignoreLevelB: Number(elements.ignoreLevelB.checked),
    ignoreLevelC: Number(elements.ignoreLevelC.checked),
  };
  const datas = { submitId, options };
  try {
    storeRecentLinks(url);
    setConnectionResult("正在获取数据...\n", "info");
    setButtonState(elements.submitBtn, true, "处理中...");
    setButtonState(elements.clearBtn, true);
    // 获取变更信息
    const message = await fetchApi(API_ENDPOINTS.changeInfo, { submitId });
    if (!message) {
      setConnectionResult("未获取到有效数据\n", "error");
      return;
    }
    // 显示基础信息结果容器
    showWithAnimation(elements.basicInfoContainer);
    // 填充基础信息
    const basicInfo = message.basic_info;
    const changedFiles = message.changed_files;
    // console.log(message.basic_info);
    // console.log(message.changed_files);
    elements.basicNumber.textContent = basicInfo._number || "未知";
    elements.basicBranch.textContent = basicInfo.branch || "未知";
    elements.basicChangeId.textContent = basicInfo.change_id || "未知";
    elements.basicCreated.textContent =
      basicInfo.created.match(TIME_PATTERN)[0] || "未知";
    elements.basicStatus.textContent = basicInfo.status || "未知";
    elements.basicStatus.className = STATUS_CLASSES[basicInfo.status] || "";
    elements.basicSubject.textContent = basicInfo.subject || "未知";
    // 获取提交者信息
    if (basicInfo.owner?._account_id) {
      try {
        const accountInfo = await fetchApi(API_ENDPOINTS.accountInfo, {
          account_id: basicInfo.owner._account_id,
        });
        // console.log(accountInfo);
        elements.basicSubmitter.textContent =
          accountInfo.account_info?.name || "未知";
      } catch (e) {
        console.error("获取用户信息失败:", e);
        alert("获取用户信息失败!");
        elements.basicSubmitter.textContent =
          basicInfo.owner._account_id || "未知";
      }
    }
    //显示文件变动信息容器
    showWithAnimation(elements.filesTableContainer);
    // 填充文件变动信息表格
    if (Object.keys(changedFiles).length === 0) {
      const emptyRow = document.createElement("tr");
      emptyRow.innerHTML =
        '<td colspan="6" style="text-align: center; padding: 20px;">没有文件变动信息</td>';
      elements.filesTableBody.appendChild(emptyRow);
    } else {
      const fragment = document.createDocumentFragment();
      Object.entries(changedFiles)
        .slice(1)
        .forEach(([filePath, fileInfo]) => {
          const row = document.createElement("tr");
          row.innerHTML = `
                <td>${filePath}</td>
                <td style="color: green;">${fileInfo.lines_inserted || 0}</td>
                <td style="color: red;">${fileInfo.lines_deleted || 0}</td>
            `;
          fragment.appendChild(row);
        });
      elements.filesTableBody.appendChild(fragment);
    }

    setConnectionResult("解析成功：已获取变更详情。\n", "success");
    // 获取分析结果
    try {
      setConnectionResult("代码审核中...\n", "info");
      setConnectionResult("审核可能有点慢，请稍等几分钟...\n", "info");
      const analysisResult = await fetchApi(API_ENDPOINTS.analyse, datas);
      if (Object.keys(analysisResult).length === 0) {
        setConnectionResult("代码审核结果为空!\n", "error");
        return;
      }

      //   console.log(analysisResult);

      showWithAnimation(elements.workflowContainer);
      showWithAnimation(elements.issuesDistributionContainer);
      renderIssueList(analysisResult);
      setConnectionResult("代码审核完成! 请在下方查看代码审核结果。\n", "success");
      elements.workflowContainer.scrollIntoView({
        behavior: "smooth", // 平滑滚动（移除则为瞬间定位）
        block: "start", // 容器顶部与视口顶部对齐（可选：'center' 居中对齐）
      });
      // showPopup();
    } catch (error) {
      alert("分析失败: " + error.message);
      setConnectionResult("代码审核失败！工作流出错，请重试!\n", "error");
      elements.workflowContainer.style.display = "none";
    }
  } catch (error) {
    alert("分析失败: " + error.message);
    setConnectionResult("分析失败! 请重试!\n", "error");
    elements.basicInfoContainer.style.display = "none";
    elements.filesTableContainer.style.display = "none";
    elements.workflowContainer.style.display = "none";
  } finally {
    setButtonState(elements.submitBtn, false, "解析链接");
    setButtonState(elements.clearBtn, false);
  }
}

function initEventListeners() {
  // 绑定清空按钮事件
  elements.clearBtn.addEventListener("click", clearInput);
  // 绑定抽屉关闭事件
  elements.closeDrawerBtn.addEventListener("click", closeDrawer);
  // 监听输入框内容变化
  elements.urlInput.addEventListener("input", (e) => {
    updateClearButtonVisibility();
    validateUrlOnInput(e.target.value.trim());
  });
  elements.urlInput.addEventListener("change", updateClearButtonVisibility);
  // 绑定提交事件
  elements.submitBtn.addEventListener("click", submitdata);
  // 添加回车键提交功能
  elements.urlInput.addEventListener("keyup", (event) => {
    if (event.key === "Enter") {
      elements.submitBtn.click();
    }
  });
  // 为输入框添加历史记录和键盘导航功能
  document.addEventListener("DOMContentLoaded", showHistory);
  elements.exportExcelBtn.addEventListener("click", async () => {
    try {
      await exportExcel();
    } catch (error) {
      alert("导出失败: " + error.message);
    }
  });
  // 中央弹窗OK按钮点击事件
  okBtn.addEventListener("click", hidePopup);

  // 添加点击非浮窗区域隐藏浮窗的功能
  document.addEventListener("click", (e) => {
    // 检查点击的元素是否在浮窗内部
    if (elements.tooltip && !elements.tooltip.contains(e.target)) {
      // 如果浮窗正在显示，则隐藏它
      if (elements.tooltip.classList.contains("show")) {
        elements.tooltip.classList.remove("show");
        currentmouseRow = null;
      }
    }
  });
}
async function exportExcel() {
  const exportData = issue_details_datas.map((issue) => ({
    问题类型: issue.type,
    规则ID: issue.rule_id,
    描述: issue.description,
    行范围: `[${issue.line_range}]`,
    文件名: issue.filename,
    代码片段: issue.code_snippet,
    建议: issue.advice,
  }));
  const worksheet = XLSX.utils.json_to_sheet(exportData);
  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, "问题列表");
  // 设置列宽
  const wscols = [
    { wch: 10 }, // 问题类型
    { wch: 10 }, // 规则ID
    { wch: 30 }, // 描述
    { wch: 10 }, // 行范围
    { wch: 20 }, // 文件名
    { wch: 40 }, // 代码片段（加宽列宽）
    { wch: 40 }, // 建议（加宽列宽）
  ];
  worksheet["!cols"] = wscols;
  XLSX.writeFile(
    workbook,
    `问题列表_${new Date().toLocaleDateString().replace(/\//g, "-")}.xlsx`
  );
}

function initchart(s_count, a_count, bc_count, total) {
  elements.issuesDistributionContainer.style.display = "block";
  renderPiechart(s_count, a_count, bc_count, total);
}

function positionCenterTextByPercentage(chartInstance) {
  const centerTextEl = elements.centerText;
  const container = chartInstance.canvas.parentElement; // 饼图父容器（定位上下文）

  // 容错：确保容器和图表存在
  if (!centerTextEl || !container || !chartInstance.chartArea) {
    centerTextEl.style.display = "none";
    return;
  }

  // 1. 获取图表区域（chartArea 是 Chart.js 提供的有效绘制区域）
  const { left: chartLeft, top: chartTop, width: chartWidth, height: chartHeight } = chartInstance.chartArea;

  // 2. 计算圆环中心相对于「图表区域」的百分比
  const centerXPercent = ((chartLeft + chartWidth / 2) / chartInstance.canvas.offsetWidth) * 100; // X轴百分比
  const centerYPercent = ((chartTop + chartHeight / 2) / chartInstance.canvas.offsetHeight) * 100; // Y轴百分比

  // 3. 文本自身居中：通过 transform 偏移自身50%（避免计算文本宽高）
  centerTextEl.style.left = `${centerXPercent}%`;
  centerTextEl.style.top = `${centerYPercent}%`;
  centerTextEl.style.transform = "translate(-50%, -50%)"; // 关键：让文本中心对齐百分比坐标
  centerTextEl.style.transformOrigin = "center"; // 确保旋转等变换不影响定位

  // 4. 基础样式确保可见
  centerTextEl.style.position = "absolute";
  centerTextEl.style.display = "block";
  centerTextEl.style.zIndex = 10;
}

function renderPiechart(s_count, a_count, bc_count, total) {
  const issuesDistributionCtx =
    elements.issuesDistributionChartPie.getContext("2d");
  if (issuesDistributionInstancePie) {
    issuesDistributionInstancePie.destroy();
    issuesDistributionInstancePie = null;
  }

  // 设置canvas父容器的高度
  elements.issuesDistributionChartPie.parentElement.style.height = "300px";

  issuesDistributionInstancePie = new Chart(issuesDistributionCtx, {
    type: "doughnut",
    data: {
      labels: ["S级", "A级", "B/C级"],
      datasets: [
        {
          data: [s_count, a_count, bc_count],
          backgroundColor: [
            "#ef4444", // 红色
            "#f59e0b", // 橙色
            "#2563eb", // 蓝色
          ],
          borderWidth: 0,
          hoverOffset: 4,
        },
      ],
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      cutout: "50%",
      layout: {
        padding: {
          left: 200,
          right: 300, // 右侧内边距，增加此值会增大图表与右侧图例的距离
        },
      },
      plugins: {
        legend: {
          position: "right",
          labels: {
            padding: 20,
            usePointStyle: true,
            pointStyle: "circle",
            generateLabels: function (chart) {
              const data = chart.data;
              if (data.labels.length && data.datasets.length) {
                return data.labels.map(function (label, i) {
                  const value = data.datasets[0].data[i];
                  const percentage = ((value / total) * 100).toFixed(1);
                  const meta = chart.getDatasetMeta(0);
                  const style = meta.controller.getStyle(i);

                  return {
                    text: `${label}: ${value} 项`,
                    fillStyle: style.backgroundColor,
                    strokeStyle: style.borderColor,
                    lineWidth: style.borderWidth,
                    hidden:
                      isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
                    index: i,
                    color: `#${CENTERTEXT_CLASSES[label]}`,
                  };
                });
              }
              return [];
            },
            // 图例样式
            font: {
              size: 15,
            },
          },
        },
        tooltip: {
          backgroundColor: "rgba(255, 255, 255, 0.9)",
          titleColor: "#1F2937",
          bodyColor: "#4B5563",
          borderColor: "#E5E7EB",
          borderWidth: 1,
          padding: 12,
          boxPadding: 6,
          usePointStyle: true,
          callbacks: {
            label: function (context) {
              updateCenterText(context, total);
              return `${context.label}: ${context.raw}项`;
            },
          },
        },
      },
      // 鼠标移动事件监听
      onHover: function (event, elements) {
        // 当鼠标移出所有扇区时清空中心文本
        if (elements.length === 0) {
          const centerText = document.getElementById("centerText");
          centerText.innerHTML = ""; // 清空文本
        }
      },
    },
  });

  // 初始化时显示第一个扇区的信息
  if (s_count > 0) {
    const firstContext = {
      raw: s_count,
      label: "S级"
    };
    updateCenterText(firstContext, total);
  } else if (a_count > 0) {
    const firstContext = {
      raw: a_count,
      label: "A级"
    };
    updateCenterText(firstContext, total);
  } else if (bc_count > 0) {
    const firstContext = {
      raw: bc_count,
      label: "B/C级"
    };
    updateCenterText(firstContext, total);
  } else {
    // 无数据时显示提示，避免文本空白
    elements.centerText.innerHTML = '<div style="color:#999;">无数据</div>';
  }

  // 首次定位（确保文本在正确位置）
  setTimeout(() => {
    if (issuesDistributionInstancePie) {
      positionCenterTextByPercentage(issuesDistributionInstancePie);
    }
  }, 100); // 延迟100ms，等待图表渲染完成（避免时机过早）

  // 窗口缩放时重新定位
  window.addEventListener("resize", function () {
    if (issuesDistributionInstancePie) {
      positionCenterTextByPercentage(issuesDistributionInstancePie);
    }
  });
}

// 更新中心文本的函数
function updateCenterText(context, total) {
  const percentage = Math.round((context.raw / total) * 100);
  elements.centerText.innerHTML = `
        <div style="font-size: 24px; font-weight: bold; color:#${CENTERTEXT_CLASSES[context.label]
    }">${percentage}%</div>
        <div style="font-size: 14px; color: #666;">${context.label}</div>
        <div style="font-size: 12px; color: #999; margin-top: 5px;">共 ${context.raw
    } 项</div>
    `;
}

// 存储最近提交的五条链接
const storeRecentLinks = (link) => {
  let links = JSON.parse(localStorage.getItem("recentLinks") || "[]");
  const linkExistsIndex = links.indexOf(link);
  if (linkExistsIndex !== -1) {
    links.splice(linkExistsIndex, 1);
  }
  links.unshift(link);
  // 保留最多五条
  links = links.slice(0, 5);
  localStorage.setItem("recentLinks", JSON.stringify(links));
};

function showHistory() {
  const input = document.querySelector('input[type="text"]');
  if (!input) return;

  let selectedIndex = -1;
  let dropdown = null;

  input.addEventListener("click", (e) => {
    e.stopPropagation(); // 防止事件冒泡导致立即关闭
    showRecentLinks();
  });

  function showRecentLinks() {
    removeDropdown();

    const recentLinks = JSON.parse(localStorage.getItem("recentLinks") || "[]");
    if (recentLinks.length === 0) return;

    dropdown = document.createElement("div");
    dropdown.id = "recentLinksDropdown";
    dropdown.style.position = "absolute";
    dropdown.style.backgroundColor = "#fff";
    dropdown.style.minWidth = `${input.offsetWidth}px`;
    dropdown.style.boxShadow = "0px 8px 16px 0px rgba(0,0,0,0.2)";
    dropdown.style.zIndex = "1000";
    dropdown.style.borderRadius = "4px";
    dropdown.style.marginTop = "4px";
    dropdown.style.maxHeight = "200px";
    dropdown.style.overflowY = "auto";

    recentLinks.forEach((link, index) => {
      const linkElement = document.createElement("a");
      linkElement.href = "#";
      linkElement.textContent = link;
      linkElement.dataset.index = index;
      linkElement.style.display = "block";
      linkElement.style.padding = "8px 12px";
      linkElement.style.textDecoration = "none";
      linkElement.style.color = "#333";
      linkElement.style.whiteSpace = "nowrap";
      linkElement.style.overflow = "hidden";
      linkElement.style.textOverflow = "ellipsis";

      // 鼠标悬停效果
      linkElement.addEventListener("mouseover", () => {
        selectedIndex = index;
        highlightSelectedItem();
      });

      linkElement.addEventListener("click", (e) => {
        e.preventDefault();
        e.stopPropagation();
        input.value = link;
        removeDropdown();
      });

      dropdown.appendChild(linkElement);
    });

    const rect = input.getBoundingClientRect();
    dropdown.style.top = `${rect.bottom + window.scrollY}px`;
    dropdown.style.left = `${rect.left + window.scrollX}px`;

    document.body.appendChild(dropdown);
    selectedIndex = -1;
  }

  // 移除下拉框
  function removeDropdown() {
    const existingDropdown = document.getElementById("recentLinksDropdown");
    if (existingDropdown) {
      existingDropdown.remove();
      dropdown = null;
      selectedIndex = -1;
    }
  }

  // 高亮选中的项
  function highlightSelectedItem() {
    if (!dropdown) return;

    // 移除所有项的高亮
    const items = dropdown.querySelectorAll("a");
    items.forEach((item) => {
      item.style.backgroundColor = "";
      item.style.color = "#333";
    });

    // 高亮当前选中项
    if (selectedIndex >= 0 && selectedIndex < items.length) {
      items[selectedIndex].style.backgroundColor = "var(--primary-color)";
      items[selectedIndex].style.color = "white";
      // 自动滚动到可见区域
      items[selectedIndex].scrollIntoView({ block: "nearest" });
    }
  }

  // 点击文档其他地方关闭下拉框
  document.addEventListener("click", (e) => {
    const isClickInsideInput = input.contains(e.target);
    const isClickInsideDropdown = dropdown && dropdown.contains(e.target);

    if (!isClickInsideInput && !isClickInsideDropdown) {
      removeDropdown();
    }
  });

  // 键盘导航
  input.addEventListener("keydown", (e) => {
    // 如果下拉框不存在，按上/下键时显示下拉框
    if (!dropdown && (e.key === "ArrowUp" || e.key === "ArrowDown")) {
      showRecentLinks();
      return;
    }

    if (!dropdown) return;

    const items = dropdown.querySelectorAll("a");
    if (items.length === 0) return;

    if (e.key === "ArrowUp") {
      e.preventDefault();
      selectedIndex = (selectedIndex - 1 + items.length) % items.length;
      highlightSelectedItem();
    } else if (e.key === "ArrowDown") {
      e.preventDefault();
      selectedIndex = (selectedIndex + 1) % items.length;
      highlightSelectedItem();
    }
    // Enter键
    else if (e.key === "Enter") {
      if (selectedIndex >= 0 && selectedIndex < items.length) {
        e.preventDefault();
        input.value = items[selectedIndex].textContent;
        removeDropdown();
      }
    }
    // Esc键关闭下拉框
    else if (e.key === "Escape") {
      removeDropdown();
    }
  });
}

function updateButtonStates() {
  // 上一页按钮状态
  if (totalItems === 0 || currentPage === 1) {
    elements.prevBtn.classList.add("disabled");
  } else {
    elements.prevBtn.classList.remove("disabled");
  }

  // 下一页按钮状态
  if (totalItems === 0 || currentPage === totalPages) {
    elements.nextBtn.classList.add("disabled");
  } else {
    elements.nextBtn.classList.remove("disabled");
  }
}

// 渲染当前页表格数据
function renderissueTable(page, datas) {
  elements.analyseTableBody.innerHTML = "";

  // 处理空数据状态
  if (datas.length === 0) {
    const emptyRow = document.createElement("tr");
    emptyRow.innerHTML =
      '<td colspan="5" style="text-align: center; padding: 20px;">没有匹配的问题数据</td>';
    elements.analyseTableBody.appendChild(emptyRow);
    updateButtonStates();
    updatePaginationInfo();
    return;
  }
  const sortedData = sortData(datas);
  const startIndex = (page - 1) * itemsPerPage;
  const endIndex = Math.min(startIndex + itemsPerPage, totalItems);
  const currentData = sortedData.slice(startIndex, endIndex);
  const fragment = document.createDocumentFragment();
  currentData.forEach((item) => {
    appendIssueRow(item, fragment);
  });
  elements.analyseTableBody.appendChild(fragment);

  updateButtonStates();
  updatePaginationInfo();
  updateSortIndicators();
}

// 排序数据
function sortData(data) {
  if (sortField === "type") {
    const typeOrder = ["S级", "A级", "B级", "C级"];
    const orderMap = new Map(typeOrder.map((item, index) => [item, index]));

    return data.sort((a, b) => {
      const indexA = orderMap.get(a[sortField]) ?? typeOrder.length;
      const indexB = orderMap.get(b[sortField]) ?? typeOrder.length;

      const comparison = indexA - indexB;
      return sortDirection === "asc" ? comparison : -comparison;
    });
  }
  return data.sort((a, b) => {
    if (a[sortField] < b[sortField]) {
      return sortDirection === "asc" ? -1 : 1;
    }
    if (a[sortField] > b[sortField]) {
      return sortDirection === "asc" ? 1 : -1;
    }
    return 0;
  });
}

// 更新排序指示器
function updateSortIndicators() {
  const tableHeaders = elements.datatable.querySelectorAll("th");
  tableHeaders.forEach((header) => {
    const indicator = header.querySelector(".sort-indicator");
    if (!indicator) {
      return;
    }
    if (header.dataset.sort === sortField) {
      header.classList.add("sorted");
      indicator.className = `fas sort-indicator ${sortDirection === "asc" ? "fa-sort-up" : "fa-sort-down"
        }`;
    } else {
      header.classList.remove("sorted");
      indicator.className = "fas sort-indicator fa-sort";
    }
  });
}

// 过滤数据
function filterData() {
  const searchTerm = elements.searchBox.value.toLowerCase();
  const rank = elements.rankFilter.value;
  const filename = elements.fileFilter.value;

  filteredData = issue_details_datas.filter((issue) => {
    // 搜索词过滤
    const matchesSearch = Object.values(issue).some((value) =>
      String(value).toLowerCase().includes(searchTerm)
    );

    // 等级过滤
    const matchesrank = !rank || issue.type === rank;

    // 文件名过滤
    const matchesFilename = !filename || issue.filename === filename;

    return matchesSearch && matchesrank && matchesFilename;
  });

  totalItems = filteredData.length;
  totalPages = Math.max(1, Math.ceil(totalItems / itemsPerPage)); // 确保至少有1页
  // 重置到第一页
  currentPage = 1;
  renderissueTable(currentPage, filteredData);
}

// 更新分页信息
function updatePaginationInfo() {
  elements.pageNumbersContainer.innerHTML = "";
  if (totalItems == 0) {
    document.getElementById("pageRange").textContent = `${0}-${0}`;
  } else {
    const start = (currentPage - 1) * itemsPerPage + 1;
    const end = Math.min(currentPage * itemsPerPage, totalItems);
    document.getElementById("pageRange").textContent = `${start}-${end}`;
  }
  document.getElementById("totalItems").textContent = totalItems;
  let startPage = Math.max(1, currentPage - 2);
  let endPage = Math.min(totalPages, startPage + 4);

  // 确保始终显示5个页码（除非总页数少于5）
  if (endPage - startPage < 4 && totalPages > 5) {
    startPage = Math.max(1, endPage - 4);
  }

  // 添加首页按钮（当不是第一页时）
  if (startPage > 1) {
    const firstBtn = createPageButton(1, "首页");
    elements.pageNumbersContainer.appendChild(firstBtn);

    // 添加省略号
    if (startPage > 2) {
      elements.pageNumbersContainer.appendChild(createEllipsis());
    }
  }

  // 添加中间页码
  for (let i = startPage; i <= endPage; i++) {
    // console.log("更新中间页码");
    const button = document.createElement("button");
    button.className = `medium-page-btn ${i === currentPage ? "current" : ""}`;
    button.textContent = i;
    elements.pageNumbersContainer.appendChild(button);
  }

  // 添加末页按钮（当不是最后一页时）
  if (endPage < totalPages) {
    // 添加省略号
    if (endPage < totalPages - 1) {
      elements.pageNumbersContainer.appendChild(createEllipsis());
    }

    const lastBtn = createPageButton(totalPages, "末页");
    elements.pageNumbersContainer.appendChild(lastBtn);
  }

  bindPageNumberEvents();
}

function createPageButton(pageNum, text = null) {
  const button = document.createElement("button");
  button.className = `page-btn ${pageNum === currentPage ? "current" : ""}`;
  button.textContent = text || pageNum;
  button.dataset.page = pageNum;
  return button;
}

function createEllipsis() {
  const ellipsis = document.createElement("span");
  ellipsis.className = "page-ellipsis";
  ellipsis.textContent = "...";
  return ellipsis;
}

function bindPageNumberEvents() {
  // 先移除所有现有事件监听，避免重复绑定
  const buttons = elements.pageNumbersContainer.querySelectorAll("button");
  buttons.forEach((button) => {
    // 移除所有事件监听器（通过克隆元素实现）
    const newButton = button.cloneNode(true);
    button.parentNode.replaceChild(newButton, button);
  });

  // 重新绑定事件
  elements.pageNumbersContainer
    .querySelectorAll("button")
    .forEach((button) => {
      button.addEventListener("click", () => {
        let pageNum = 0;
        if (button.textContent === "末页") {
          pageNum = totalPages;
        } else if (button.textContent === "首页") {
          pageNum = 1;
        } else {
          pageNum = button.textContent;
        }

        if (parseInt(pageNum) !== currentPage) {
          // 避免重复点击当前页
          currentPage = parseInt(pageNum);
          renderissueTable(currentPage, filteredData);
        }
      });
    });
}

// 初始化
loadDOMElements();
initEventListeners();
